import axios from 'axios';
// import type { AxiosRequestConfig, AxiosResponse } from 'axios';
// import type { LocationQueryRaw } from 'vue-router';
import { ElMessage } from 'element-plus';
import { getToken } from '@/utils/auth';
import { getUTCStr } from '@/utils/timezone';
import { SM4Encrypt } from '@/utils/encryption/sm4.ts';
import defaultSettings from '@/config/sys-settings';
import router from '@/router';
// import { useUserStore } from '@/store';
import { getSign } from './request-sign';
import { verifyRequest, verifyResponse, verifyUrl } from './verify-api';

export interface HttpResponse<T = unknown> {
	status: number;
	msg: string;
	message?: string;
	code: number;
	data: T;
}

export interface IFusionBiz {
	timeZone?: string;
	timeFormat?: string;
	portalId?: string;
	buttonId?: string;
	apiCrypto?: any;
}

if (import.meta.env.VITE_APP_BASE_API) {
	axios.defaults.baseURL = import.meta.env.VITE_APP_BASE_API || './api';
	axios.defaults.withCredentials = true;
	axios.defaults.timeout = 10000;
}

// 是否解密响应
const responseEncryptMap = new Map();

axios.interceptors.request.use(
	(config: any) => {
		let FusionBiz: IFusionBiz = {};
		// transfer timezone by header
		const UTC = getUTCStr(defaultSettings.timezone);
		FusionBiz.timeZone = UTC;
		FusionBiz.timeFormat = 'yyyy-MM-dd HH:mm:ss';

		const url = config.url || '';
		const len = url.indexOf('?');
		// To determine whether API needs to be encrypted here, it must start with '/api'
		const subUrl =
			(len > -1 ? url.substring(url.indexOf('/', 1), len) : url.substring(url.indexOf('/', 1))) ||
			url;
		const requestEncrypt = verifyRequest(config) && defaultSettings.requestEncrypt;
		const responseEncrypt = verifyResponse(config) && defaultSettings.responseEncrypt;
		const apiCrypto = {
			requestEncrypt: {
				encrypt: requestEncrypt,
				ignoreUrl: requestEncrypt ? '' : subUrl
			},
			responseEncrypt: {
				encrypt: responseEncrypt,
				ignoreUrl: responseEncrypt ? '' : subUrl
			}
		};
		FusionBiz = { ...FusionBiz, apiCrypto };
		responseEncryptMap.set(config.url, apiCrypto.responseEncrypt.encrypt);

		config.headers = config.headers || {};
		config.headers['Fusion-Biz'] = SM4Encrypt(JSON.stringify(FusionBiz));

		if (verifyUrl(config, 'sign')) {
			config.params = getSign(config.params);
		} else {
			config.headers['Fusion-Auth'] = getToken() || '';
		}

		if (apiCrypto.requestEncrypt.encrypt && !apiCrypto.requestEncrypt.ignoreUrl) {
			// config = encrypt(config);
		}
		return config;
	},
	(error) => {
		// do something
		return Promise.reject(error);
	}
);

axios.interceptors.response.use(
	(response: any) => {
		if (responseEncryptMap.get(response.config.url)) {
			// response = decrypt(response);
		}

		if (response.config.responseType === 'blob') {
			return response;
		}

		const res = response.data;

		if (verifyUrl(response.config, 'cMsg')) {
			return res;
		}

		if (res.code !== 8000000) {
			if (res.message) {
				ElMessage.warning({
					message: res.message || 'Request Error',
					duration: 3 * 1000
				});
			}
			// return Promise.reject(response);
		}

		// 将数据中HH:mm这类UTC-8时区转为当前时区
		// if (res.data && getUTCStr(store.getters[types.TIMEZONE]) !== 'UTC+08:00') {
		//   res.data = JSON.parse(matchUTCToTime(JSON.stringify(res.data)))
		// }

		return res;
	},
	(error) => {
		let message = '';
		// const errMsg = error.message;
		const errMsg = error.toJSON();
		if (errMsg) {
			// const userStore = useUserStore();
			switch (errMsg.status) {
				case 400:
					message = '错误请求';
					break;
				case 401:
					message = '未授权';
					message = error.response?.data?.message || '未授权';
					// userStore.logoutCallBack();
					if (router.currentRoute.value?.name !== 'login') {
						const path = `/login${window.location?.search ? window.location?.search : ''}`;
						router.push(path);
					}
					break;
				case 403:
					message = '拒绝访问';
					break;
				case 404:
					message = '请求错误,未找到该资源';
					break;
				case 405:
					message = '请求方法未允许';
					break;
				case 408:
					message = '请求超时';
					break;
				case 500:
					message = '服务器端出错';
					break;
				case 501:
					message = '网络未实现';
					break;
				case 502:
					message = '网络错误';
					break;
				case 503:
					message = '服务不可用';
					break;
				case 504:
					message = '网络超时';
					break;
				case 505:
					message = 'http版本不支持该请求';
					break;
				default:
					message = `连接错误${errMsg.status}`;
			}
			if (errMsg.config && verifyUrl(errMsg.config, 'cMsg')) {
				message = '';
			}
		}
		if (message) {
			ElMessage.error({
				message: message || 'Request Error',
				duration: 3 * 1000
			});
		}
		return Promise.reject(error);
	}
);
